﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using NoteHelper.IBusiness;
using NoteHelper.Model;

namespace NoteHelper.Business.IbatisImpl
{
    public class ArticleManagerImpl : ManagerBase<Article>, IArticleManager
    {
        private readonly IArticleAttributeManager _articleAttributeManager;
        private readonly IArticleNoteManager _articleNoteManager;
        private readonly IArticleTypeManager _articleTypeManager;

        public ArticleManagerImpl(IArticleAttributeManager attributeManager, IArticleNoteManager noteManager, IArticleTypeManager articleTypeManager)
        {
            _articleAttributeManager = attributeManager;
            _articleNoteManager = noteManager;
            _articleTypeManager = articleTypeManager;
        }

        public DataSet GetArticle(int objectId)
        {
            var entity = GetFullEntity(objectId);
            var ds = entity.ToDataSet();
            ds.Tables.Add(entity.Notes.ToDataTable("Notes"));
            var attrList = entity.Attributes.Select(t => t.ArticleType).ToList();
            ds.Tables.Add(attrList.ToDataTable("Attributes"));

            return ds;
        }

        private Article GetFullEntity(int id)
        {
            var entity = Get(id);
            if (entity == null) return new Article();

            entity.Attributes = _articleAttributeManager.GetArticleAttributeList(entity.ObjectID);
            entity.Notes = _articleNoteManager.GetArticleNoteList(entity.ObjectID);
            return entity;
        }

        [Transaction]
        public int SaveOrUpdateArticle(DataSet ds, int objectId)
        {
            int iResult;
            if (objectId > 0)
            {
                UpdateArticle(ds, objectId);
                iResult = objectId;
            }
            else
            {
                iResult = AddNewArticle(ds);
            }

            return iResult;
        }

        private void UpdateArticleTypes(DataTable table)
        {
            foreach (DataRow row in table.Rows)
            {
                int objectId = (int)row["ObjectID"];
                if (objectId == 0)
                {
                    var entity = _articleTypeManager.SaveIfNotExists(row["ChName"].ToString());
                    row["ObjectID"] = entity.ObjectID;
                }
            }
        }

        private int AddNewArticle(DataSet ds)
        {
            UpdateArticleTypes(ds.Tables["Attributes"]);

            Article entity = new Article
            {
                Description = ds.Tables["Article"].Rows[0]["Description"].ToString(),
                FileUrl = ds.Tables["Article"].Rows[0]["FileUrl"].ToString()
            };
            entity.ObjectID = (int)Add(entity);

            // 添加明细
            foreach (DataRow dataRow in ds.Tables["Notes"].Rows)
            {
                var note = new ArticleNote
                {
                    ObjectID = (int)dataRow["ObjectID"],
                    Description = dataRow["Description"].ToString()
                };
                note.Article = entity;
                note.ArticleID = entity.ObjectID;
                _articleNoteManager.Add(note);
            }

            // 添加标签
            foreach (DataRow row in ds.Tables["Attributes"].Rows)
            {
                var attribute = new ArticleAttribute()
                {
                    Article = entity,
                    ArticleID = entity.ObjectID,
                    ArticleTypeID = (int)row["ObjectID"]
                };
                _articleAttributeManager.Add(attribute);
            }

            return entity.ObjectID;
        }

        private int UpdateArticle(DataSet ds, int objectId)
        {
            UpdateArticleTypes(ds.Tables["Attributes"]);

            Article entity = GetFullEntity(objectId);
            entity.Description = ds.Tables["Article"].Rows[0]["Description"].ToString();
            entity.FileUrl = ds.Tables["Article"].Rows[0]["FileUrl"].ToString();
            entity.LastUpdateTime = DateTime.Now;
            Update(entity);

            UpdateArticleAttributeList(ds, entity);
            UpdateArticleNoteList(ds, entity);

            return objectId;
        }

        private void UpdateArticleNoteList(DataSet ds, Article entity)
        {
            var noteIdList = new List<int>();
            foreach (DataRow dataRow in ds.Tables["Notes"].Rows)
            {
                string description = dataRow["Description"].ToString();
                int articleNoteId = (int)dataRow["ObjectID"];
                ArticleNote note;
                if (articleNoteId == 0)
                {
                    // 添加
                    note = new ArticleNote
                    {
                        ArticleID = entity.ObjectID,
                        Description = description
                    };
                    var noteId = _articleNoteManager.Add(note);
                    note = _articleNoteManager.Get(noteId);
                    entity.Notes.Add(note);
                    noteIdList.Add(note.ObjectID);
                }
                else
                {
                    note = entity.Notes.SingleOrDefault(t => t.ObjectID == articleNoteId);
                    if (note == null) continue;
                    if (description == note.Description)
                    {
                        noteIdList.Add(articleNoteId);
                        continue;
                    }

                    // 更新
                    note.Description = description;
                    note.LastUpdateTime = DateTime.Now;
                    _articleNoteManager.Update(note);
                    noteIdList.Add(articleNoteId);
                }
            }


            var len = entity.Notes.Count;
            for (int i = len - 1; i >= 0; i--)
            {
                var note = entity.Notes[i];
                if (!noteIdList.Contains(note.ObjectID))
                {
                    _articleNoteManager.Delete(note.ObjectID);
                    entity.Notes.RemoveAt(i);
                }
            }
        }

        private void UpdateArticleAttributeList(DataSet ds, Article entity)
        {
            var articleTypeIdList = (from DataRow row in ds.Tables["Attributes"].Rows select (int)row["ObjectID"]).ToList();
            int count = entity.Attributes.Count;
            // 删除
            for (int i = count - 1; i >= 0; i--)
            {
                var item = entity.Attributes[i];
                if (!articleTypeIdList.Contains(item.ArticleTypeID))
                {
                    _articleAttributeManager.Delete(item);
                    entity.Attributes.RemoveAt(i);
                }
            }
            // 添加
            foreach (int typeId in articleTypeIdList)
            {
                if (entity.Attributes.Count(t => t.ArticleTypeID == typeId) > 0) continue;
                var newItem = new ArticleAttribute
                {
                    ArticleID = entity.ObjectID,
                    ArticleTypeID = typeId
                };
                _articleAttributeManager.Add(newItem);
                entity.Attributes.Add(newItem);
            }
        }

        public string GetFormType(string name)
        {
            if (name == "sys")
                return "NoteHelper.Sys.Sysm002";

            var formEntity = Mapper.QueryForObject("GetProjectForm", name) as ProjectForm;
            if (null == formEntity) return "";

            return formEntity.FullName;
        }

        public DataTable ListToDataTable(IList<Article> lst)
        {
            var fields = new[] { "ObjectID", "Description" };
            return lst.ToDataTable(fields);
        }
    }
}